package god;

import java.util.ArrayList;

public class J19Generic {

	public static void main(String[] args) {
		
		// 고정 크기 배열
																			// JDK 4 이하에서 사용 하던 코드
		Tiger zoo1[] = new Tiger[3];						// 호랑이를 가두기 위한 동물원
		Lion zoo2[] = new Lion[3];							// 사자를 가두기 위한 동물원
		Zibra zoo3[] = new Zibra[3];						// 얼룩말을 가두기 위한 동물원
		
		// 호랑이, 사자, 얼룩말을 가둘 수 있는 동물원
		// 상속 관계를 이용
		Animal zoo4[] = new Animal[3];				// 상속 관계 일 때는 수퍼클래스를 이용를 이용하여 한 곳에 담음
		// 호랑이, 사자, 얼룩말 뿐 아니라 언급되지
		// 않은 다른 동물들도 가둘 수 있는 동물원
		// Object 클래스는 모든 클래스의 조상
		Object zoo5[] = new Object[3];					// 상속 관계가 아닐 때는 Object 라는 조상 클래스를 이용하여 한 곳에 담음
		
		zoo1[1] = new Tiger();								// zoo1에 호랑이 한마리 가둠
		//zoo1[2] = new Zibra();								// zoo1은 타이거만 가두는 동물원이라 다른 동물을 가둘 수 없음
		
		zoo4[0] = new Tiger();								// 배열 : 동일한 유형의 여러 데이터를 다루기 위해 사용하지만
		zoo4[1] = new Lion();									// 객체 타입으로 선언하여 사용하면 다른 타입의 데이터를 넣는데는 문제가 없음
		zoo4[2] = new Zibra();								// 자동으로 업캐스팅 되어서 데이터를 넣는데는 문제가 없으나 업캐스팅 되었기 때문에 뺄 때 문제가 생김
		//zoo4[1] = new Monkey();							// 상속 관계가 아니기 때문에 들어가지 않음
		
		zoo5[0] = new Tiger();
		zoo5[1] = new Monkey();
		
		Animal animal1 = zoo4[1];
		//Lion lion1 = zoo4[1];									// zoo4[1]은 animal로 인식 되기 때문에 다운 캐스팅을 하지 않으면 animal보다 낮은 관계인 Lion에 담을 수 없음
		
		// Animal을 객체를 Lion 객체에 저장하려면 먼저 다운 캐스팅 해야 함
		Lion lion1 = (Lion) zoo4[1];
		
		// 명시적으로 다운 캐스팅을 하는게 다소 귀찮은 작업이므로 배열 보다는 컬렉션을 사용한다
		// 위와 같은 현상을 최소화 하기 위해 배열에는 단일 종류 데이터를 저장하는데 사용하는 대신 컬렉션을 사용하자
		
		// 컬렉션 (가변 크기 배열)
		ArrayList zoo6 = new ArrayList();
		zoo6.add(new Tiger());									// .add(object) : 위에 object 클래스를 이용한 것 처럼 온갖 데이터 타입을 담을 수 있음
		zoo6.add(new Lion());										// 컬렉션에서는 어떤 종류의 자료를 담을지 모르기 때문에 최상위 조상 객체인 Object 형태로 저장 및 관리하도록 설계 됨
		zoo6.add(new Zibra());									// 위 처럼 설계 되었다고 아무거나 막 넣으라는게 아니다.
		zoo6.add(new Monkey());								// 컬렉션을 사용할때도 동이한 데이터 타입으로 넣도록 한다.
		zoo6.add(new Whale());
		
		// 지네릭을 이용하면 프로그래머가 컬렉션에 사용할
		// 객체의 유형을 명확하게 지정해서 이 유형과 다른
		// 객체는 저장되지 못하게 함
		// 따라서,컴파일시 오류 확인이 빨라짐
																								// JDK 5 이상에서 사용 하는 코드
		ArrayList<Tiger> zoo7 = new ArrayList<Tiger>();		// <> 안에 집어 넣을 타입을 정의해 놓고 사용하여, 형 변환을 사용하지 않고 사용할 수 있도록 한다.
		//zoo7.add(new Lion());													// zoo6.add 는 object 라서 아무거나 다 넣을 수 있지만 
		zoo7.add(new Tiger());													// zoo7은 지네릭으로 <Tiger> 객체만 저장할 수 있도록 한정 시킴.
																								// 따라서, 예상치 못한 오류가 발생할 수 있는 가능성은 낮아짐
		
		ArrayList<Lion> zoo8 = new ArrayList<>();					// 원래 앞, 뒤의 지네릭에 모두 명시를 해줘야 했지만, JDK7 이상에서는 생략이 가능하다.	
	}

}

class Animal {
	
}

class Tiger extends Animal {
	
}

class Lion extends Animal {
	
}

class Zibra extends Animal {
	
}

class Monkey {
	
}

class Whale {
	
}